package impl

import (
	"context"

	"gitee.com/go-course/go9/projects/devcloud/cmdb/apps/resource"
	"gitee.com/go-course/go9/projects/devcloud/cmdb/apps/secret"
	"gitee.com/go-course/go9/projects/devcloud/cmdb/common/logger"
	"gitee.com/go-course/go9/projects/devcloud/cmdb/provider/tencent"
)

// 创建凭证
func (i *impl) CreateSecret(ctx context.Context, in *secret.CreateSecretRequest) (
	*secret.Secret, error) {
	if err := in.Validate(); err != nil {
		return nil, err
	}

	// 明文保存了? 不要保存,避免托库
	ins := secret.New(in)

	// 加密保存
	err := ins.EncryptAPISecret(i.encryptKey)
	if err != nil {
		return nil, err
	}

	record := struct {
		*secret.Meta
		*secret.CreateSecretRequest
	}{
		ins.Meta,
		ins.Spec,
	}
	err = i.db.WithContext(ctx).Create(record).Error
	if err != nil {
		return nil, err
	}
	return ins, nil
}

// 查询凭证详情
// 这里需不需要解密
func (i *impl) QuerySecret(ctx context.Context, in *secret.QuerySecretRequest) (
	*secret.SecretSet, error) {
	set := secret.NewSecretSet()

	query := i.db.WithContext(ctx).Table("secrets")

	err := query.Count(&set.Total).Error
	if err != nil {
		return nil, err
	}

	query = query.
		Order("create_at DESC").
		Offset(int(in.Page.ComputeOffset())).
		Limit(int(in.Page.PageSize))

	records := []struct {
		*secret.Meta
		*secret.CreateSecretRequest
	}{}

	err = query.Find(&records).Error
	if err != nil {
		return nil, err
	}

	for i := range records {
		r := records[i]
		r.Desense()
		set.Add(&secret.Secret{
			Meta: r.Meta,
			Spec: r.CreateSecretRequest,
		})
	}

	return set, nil
}

// 查询凭证详情
// 这里需不需要解密
func (i *impl) DescribeSecret(ctx context.Context, in *secret.DescribeSecretRequest) (
	*secret.Secret, error) {

	record := struct {
		*secret.Meta
		*secret.CreateSecretRequest
	}{}
	err := i.db.
		WithContext(ctx).
		Table("secrets").
		Where("id = ?", in.Id).
		First(&record).
		Error
	if err != nil {
		return nil, err
	}

	ins := secret.New(secret.NewCreateSecretRequest())
	ins.Meta = record.Meta
	ins.Spec = record.CreateSecretRequest
	return ins, nil
}

// 资源同步
func (i *impl) SyncResource(ctx context.Context, in *secret.DescribeSecretRequest) error {
	// 查询secret
	ins, err := i.DescribeSecret(ctx, in)
	if err != nil {
		return err
	}

	// 解密secret
	err = ins.DecryptAPISecret(secret.EncryptKey)
	if err != nil {
		return err
	}

	switch ins.Spec.Provider {
	case secret.PROVIDER_TENCENT_CLOUD:
		client := tencent.NewTencentClient(
			ins.Spec.ApiKey,
			ins.Spec.ApiSecret,
		)
		// 设置回调处理逻辑
		client.SetResourceHandleHook(func(ctx context.Context, res *resource.Resource) {
			_, err := i.resource.Put(ctx, res)
			if err != nil {
				logger.L().Error().Msgf("save resource error, %s", err)
			}
		})
		client.SyncHost(ctx)
	}

	return nil
}
